import math
import numpy as np
import math as m

class REGIME:
    def __init__(self, DecisionMatrix, weight, q):
        '''
        假设只有效益型
        :param DecisionMatrix: 决策矩阵
        :param wight: 属性权重
        :param q: q值
        '''
        self.matrix = DecisionMatrix
        self.weight = weight
        self.q = q

    def addition(self,Ivq1,Ivq2,q):
        '''
        加法
        :param Ivq1:区间值
        :param Ivq2:区间值
        :param q:q值
        :return:
        '''
        a,b,c,d=Ivq1[0][0],Ivq1[0][1],Ivq1[1][0],Ivq1[1][1]
        e,f,g,h=Ivq2[0][0],Ivq2[0][1],Ivq2[1][0],Ivq2[1][1]
        u1=a**q+e**q-(a**q)*(e**q)
        u2=b**q+f**q-(b**q)*(f**q)
        v1=c*g
        v2=h*d
        return ([u1,u2],[v1,v2])

    def subtraction(self,Ivq1,Ivq2,q):
        '''
        减法
        :param Ivq1:区间值
        :param Ivq2:区间值
        :param q:q值
        :return:
        '''
        a,b,c,d=Ivq1[0][0],Ivq1[0][1],Ivq1[1][0],Ivq1[1][1]
        e,f,g,h=Ivq2[0][0],Ivq2[0][1],Ivq2[1][0],Ivq2[1][1]
        u1=a*g
        u2=b*h
        v1=(c**q+e**q-(c**q)*(e**q))**(1/q)
        v2=(d**q+f**q-(d**q)*(f**q))**(1/q)
        return ([u1, u2],[v1, v2])

    def multiplication(self,Ivq1,Ivq2,q):
        '''
        乘法
        :param Ivq1:区间值
        :param Ivq2:区间值
        :param q:q值
        :return:
        '''
        a, b, c, d = Ivq1[0][0], Ivq1[0][1], Ivq1[1][0], Ivq1[1][1]
        e, f, g, h = Ivq2[0][0], Ivq2[0][1], Ivq2[1][0], Ivq2[1][1]
        u1 = a * e
        u2 = b * f
        v1 = (c ** q + g ** q - (c ** q) * (g ** q)) ** (1 / q)
        v2 = (d ** q + h ** q - (d ** q) * (h ** q)) ** (1 / q)
        return ([u1, u2], [v1, v2])

    def division(self,Ivq1,Ivq2,q):
        '''
        除法
        :param Ivq1:区间值
        :param Ivq2:区间值
        :param q:q值
        :return:
        '''
        a, b, c, d = Ivq1[0][0], Ivq1[0][1], Ivq1[1][0], Ivq1[1][1]
        e, f, g, h = Ivq2[0][0], Ivq2[0][1], Ivq2[1][0], Ivq2[1][1]
        u1 = (a ** q + g ** q - (a ** q) * (g ** q)) ** (1 / q)
        u2 = (b ** q + h ** q - (b ** q) * (h ** q)) ** (1 / q)
        v1 = c*e
        v2 = d*f
        return ([u1, u2], [v1, v2])

    def getscore(self,IVq):
        '''
        我们提出的得分函数
        :param IVq:区间值
        :param q:q值
        :return:
        '''
        a = IVq[0][0]
        b = IVq[0][1]
        c = IVq[1][0]
        d = IVq[1][1]
        return (m.log(math.fabs(a + b + c + d + 1)) + (b - a) + (d - c) ** 2 + (a - c + b - d) * m.log(3) / 2) / (
                2 * m.log(3))

    def Exponentiation(self,Ivq1,q,n):
        '''
        次方运算
        :param Ivq1:
        :param q:
        :param n:开多少次方
        :return:
        '''
        a, b, c, d = Ivq1[0][0], Ivq1[0][1], Ivq1[1][0], Ivq1[1][1]
        u1 = a ** n
        u2 = b ** n
        v1 =(1-((1-(c**q))**n))**(1/q)
        v2 =(1-((1-(d**q))**n))**(1/q)
        return ([u1, u2], [v1, v2])

    def getMarginalUtilityScore(self,NormalizedMatrix):
        '''
        获取边际效用得分
        :param NormalizedMatrix:规范化矩阵
        :return:
        '''
        ScoreMatrix=[]
        for Row in range(len(NormalizedMatrix)):
            Scoreline=[]
            for Column in range(len(NormalizedMatrix[0])):
                t=self.getscore(NormalizedMatrix[Row][Column])
                Scoreline.append(t)
            ScoreMatrix.append(Scoreline)
        return ScoreMatrix

    def getFinalUtilityScore(self,ScoreMatrix,Weight):
        '''
        获取最终效用得分
        :param ScoreMatrix: 得分矩阵
        :param Weight: 权重
        :return:
        '''
        U = []
        for Row in range(len(ScoreMatrix)):
            u0=0
            for Column in range(len(ScoreMatrix[0])):
                u0+=Weight[Column]*ScoreMatrix[Row][Column]
            U.append(math.fabs(u0))
        return U

    def RegimeMatrix(self, NormalizedMatrix, Weight):
        '''
        制度矩阵
        :param NormalizedMatrix: 区间值矩阵
        :param Weight: 权重
        :return:
        '''
        eflj = []
        sum = [0, 0, 0, 0]
        rfj = [0, 0, 0, 0]
        rlj = [0, 0, 0, 0]

        for f in range(5):
            next = []
            for l in range(5):
                sum[0], sum[1], sum[2], sum[3] = 0, 0, 0, 0
                for j in range(5):
                    rfj[0] = NormalizedMatrix[f][j][0][0]
                    rfj[1] = NormalizedMatrix[f][j][0][1]
                    rfj[2] = NormalizedMatrix[f][j][1][0]
                    rfj[3] = NormalizedMatrix[f][j][1][1]

                    rlj[0] = NormalizedMatrix[l][j][0][0]
                    rlj[1] = NormalizedMatrix[l][j][0][1]
                    rlj[2] = NormalizedMatrix[l][j][1][0]
                    rlj[3] = NormalizedMatrix[l][j][1][1]
                    for k in range(4):
                        if rfj[k] - rlj[k] == 0:
                            sum[k] = 0
                        else:
                            if rfj[k] - rlj[k] < 0:
                                sum[k] = -1.0*Weight[j]
                            else:
                                sum[k] = 1.0*Weight[j]
                    # 获取个体
                    sum_small = ([sum[0], sum[1]], [sum[2], sum[3]])
                    # 累加
                    if j == 0:
                        sum_avg = sum_small
                    else:
                        sum_avg = self.addition(sum_avg, sum_small, self.q)

                # 计算好的矩阵进行存储
                next.append(sum_avg)
            eflj.append(next)
        return eflj

    def getResult(self):
        '''
        最终结果
        :param Matrix:
        :param q:
        :return:
        '''
        Matrix=self.RegimeMatrix(self.matrix,self.weight)

        ScoreMatrix=self.getMarginalUtilityScore(Matrix)
        U=self.getFinalUtilityScore(ScoreMatrix, self.weight)
        U=[i/sum(U) for i in U]
        return U



if __name__ == "__main__":
    Matrix = np.array([[([0.58, 0.75], [0.1, 0.2]), ([0.7, 0.78], [0.2, 0.3]), ([0.5, 0.78], [0.1, 0.2]),
                        ([0.65, 0.7], [0.3, 0.35]), ([0.4, 0.5], [0.5, 0.6])],
                       [([0.5, 0.6], [0.1, 0.2]), ([0.75, 0.78], [0.2, 0.3]), ([0.6, 0.78], [0.1, 0.15]),
                       ([0.7, 0.8], [0.2, 0.3]), ([0.5, 0.6], [0.4, 0.5])],
                       [([0.5, 0.78], [0.1, 0.2]), ([0.6, 0.7], [0.3, 0.4]), ([0.7, 0.78], [0.2, 0.3]), ([0.6, 0.7], [0.3, 0.4]),
                       ([0.35, 0.45], [0.5, 0.65])],
                       [([0.75, 0.780], [0.2, 0.3]), ([0.6, 0.75], [0.2, 0.3]), ([0.7, 0.78], [0.2, 0.3]),
                       ([0.55, 0.65], [0.3, 0.4]), ([0.35, 0.4], [0.6, 0.65])],
                       [([0.6, 0.75], [0.3, 0.4]), ([0.5, 0.6], [0.4, 0.5]), ([0.6, 0.7], [0.3, 0.4]), ([0.5, 0.6], [0.4, 0.5]),
                       ([0.1, 0.2], [0.4, 0.5])]])
    weight = (0.1, 0.175, 0.25, 0.35, 0.125)

    maut = REGIME(Matrix, weight, 1)
    result = maut.getResult()
    print(f'U={np.round(result,4)}')

